package com.hdu.atomic;

import sun.misc.Unsafe;

import java.util.ArrayList;
import java.util.List;


public class MyAtomicInteger {

    static int ans = 0;

    public static void main(String[] args) {
        test1();
        test2();
    }


    public static void test2() {
        MyAtomicInteger myAtomicInteger = new MyAtomicInteger();
        List<Thread> ts = new ArrayList<>();
        for (int i = 0; i < 100000; i++) {
            ts.add(
                    new Thread(() -> myAtomicInteger.increment(1))
            );
        }
        ts.forEach(Thread::start);
        ts.forEach(t -> {
            try {
                t.join();
            } catch (InterruptedException e) {
                e.printStackTrace();
            }
        });
        System.out.println(myAtomicInteger.getValue());
    }

    public static void test1() {
        List<Thread> ts = new ArrayList<>();
        for (int i = 0; i < 100000; i++) {
            ts.add(
                    new Thread(() -> ans++)
            );
        }
        ts.forEach(Thread::start);
        ts.forEach(t -> {
            try {
                t.join();
            } catch (InterruptedException e) {
                e.printStackTrace();
            }
        });
        System.out.println(ans);
    }

    private volatile int value;
    private static final long VALUE_OFFSET;
    private static final Unsafe UNSAFE;

    static {
        UNSAFE = UnsageUtils.getUnsafe();
        try {
            VALUE_OFFSET = UNSAFE.objectFieldOffset(MyAtomicInteger.class.getDeclaredField("value"));
        } catch (NoSuchFieldException e) {
            throw new RuntimeException(e);
        }
    }


    public int getValue() {
        return value;
    }


    public void increment(int val) {
        while (true) {
            int preV = value;
            if (UNSAFE.compareAndSwapInt(this, VALUE_OFFSET, preV, preV + val)) {
                return;
            }
        }
    }
}
